package work.linruchang.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import work.linruchang.util.bean.CommitInfo;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author LinRuChang
 * @version 1.0
 * @date 2023/07/27
 * @since 1.8
 **/
public class GitBlitUtil {

    /**
     * 登录用户的Cookie
     *
     * @param gitBlitIp   GitBlit的IP
     * @param gitBlitPort GitBlit的端口
     * @param userName    用户名
     * @param password    密码
     * @return
     */
    public static String gitBlitUserCookieValue(String gitBlitIp, String gitBlitPort, String userName, String password) {
        // 1. 校验
        Assert.isTrue(StrUtil.isAllNotBlank(gitBlitIp, gitBlitPort, userName, password), "参数不得为空，请检查");

        // 2. 获取登录用户的cookie以及session
        Dict formData = Dict.create()
                .set("wicket:bookmarkablePage", ":com.gitblit.wicket.pages.MyDashboardPage")
                .set("id1_hf_0", "")
                .set("username", "admin")
                .set("password", "admin");

        HttpResponse httpResponse = HttpUtil.createPost(StrUtil.format("http://{}:{}/?wicket:interface=:0:userPanel:loginForm::IFormSubmitListener::", gitBlitIp, gitBlitPort))
                .form(formData)
                .execute();
        List<String> cookies = httpResponse.headerList("Set-Cookie");
        String cookieValue = CollUtil.join(cookies, ";");

        return cookieValue;
    }

    /**
     * 获取某个仓库的分支
     *
     * @param gitBlitIp   GitBlit的IP
     * @param gitBlitPort GitBlit的端口
     * @param userName    用户名
     * @param password    密码
     * @param resp        仓库名
     * @return
     */
    public static List<String> gitBlitBranchsByResp(String gitBlitIp, String gitBlitPort, String userName, String password, String resp) {

        // 1. 校验
        Assert.isTrue(StrUtil.isAllNotBlank(gitBlitIp, gitBlitPort, userName, password, resp), "参数不得为空，请检查");

        // 2. 用户Cookie
        String cookieValue = gitBlitUserCookieValue(gitBlitIp, gitBlitPort, userName, password);


        HttpResponse resphttpResponse = HttpUtil.createGet(StrUtil.format("http://{}:{}/branches/{}.git", gitBlitIp, gitBlitPort, resp))
                .header("Cookie", cookieValue, true)
                .execute();
        String respInfoBody = resphttpResponse.body();

        // 3. 获取仓库的分支信息
        Element repositorynavbarElement = CollUtil.get(Jsoup.parse(respInfoBody).select("body>.container"), 1);
        Elements branchElements = repositorynavbarElement != null ? repositorynavbarElement.select("table tr>td:nth-child(2)") : new Elements();

        List<String> branchNames = branchElements
                .stream()
                .map(Element::text)
                .map(StrUtil::trim)
                .distinct()
                .collect(Collectors.toList());


        return branchNames;
    }


    /**
     * 获取某个仓库的某个分支的提交记录信息（第一页显示50个、从第二页开始最多显示20个提交记录）
     *
     * @param gitBlitIp   GitBlit的IP
     * @param gitBlitPort GitBlit的端口
     * @param userName    用户名
     * @param password    密码
     * @param resp        仓库名
     * @param branchName  分支名 不传默认master
     * @param pageNo      提交记录的页码，从1开始，-1则查全部记录 == 不传默认查第一页
     * @return
     */
    public static List<CommitInfo> getRespCommits(String gitBlitIp, String gitBlitPort, String userName, String password, String resp, String branchName, Integer pageNo) {
        pageNo = Convert.toInt(pageNo, 1);
        branchName = StrUtil.blankToDefault(branchName, "master");
        // 1. 校验
        Assert.isTrue(StrUtil.isAllNotBlank(gitBlitIp, gitBlitPort, userName, password, resp, branchName), "参数不得为空，请检查");

        // 2. 登录信息
        String userCookieValue = gitBlitUserCookieValue(gitBlitIp, gitBlitPort, userName, password);

        // 3. 获取提交记录
        List<CommitInfo> result = CollUtil.newArrayList();

        // 当前准备开始的页码，结束的页码
        Integer currentStartPageNo = pageNo < 1 ? 1 : pageNo;
        Integer endPageNo = pageNo;

        while (true) {


            HttpResponse commitHtmlHttpResponse = HttpUtil.createGet(StrUtil.format("http://{}:{}/log/{}.git/{}?pg={}", gitBlitIp, gitBlitPort, resp, branchName, currentStartPageNo))
                    .header("Cookie", userCookieValue, true)
                    .execute();

            Document htmlParse = Jsoup.parse(commitHtmlHttpResponse.body());

            Elements commitElements = htmlParse.select(".container table[class='pretty'] tr[class*='commit']");

            List<CommitInfo> currentPageResult = commitElements.stream()
                    .map(commitElement -> {

                        // 信息获取
                        String date1 = StrUtil.trim(commitElement.selectFirst(".date span[title]").attr("title"));
                        String date2 = StrUtil.trim(commitElement.selectFirst(".date span[title]").text());
                        String date = ReUtil.isMatch("\\d{4}-\\d{2}-\\d{2}", date1) ? date1 : date2;

                        String author = StrUtil.trim(commitElement.selectFirst(".author").text());
                        String describe = StrUtil.trim(commitElement.selectFirst(".message .subject").text());
                        String commitId = StrUtil.trim(commitElement.selectFirst(".shortsha1").attr("title"));

                        // 对象构建
                        CommitInfo commitInfo = new CommitInfo().setCommitId(commitId)
                                .setDate(date)
                                .setAuthor(author)
                                .setDescribe(describe);
                        return commitInfo;
                    })
                    .collect(Collectors.toList());

            // 当前页的结果
            result.addAll(currentPageResult);


            // 结束标志
            if (currentStartPageNo == endPageNo || CollUtil.isEmpty(currentPageResult)) {
                break;
            }

            // 下一页页码
            currentStartPageNo++;
        }


        return result;
    }


    /**
     * 获取某个用户下支持的仓库
     *
     * @param gitBlitIp   GitBlit的IP
     * @param gitBlitPort GitBlit的端口
     * @param userName    用户名
     * @param password    密码
     * @return
     */
    public static List<String> gitBlitUserResps(String gitBlitIp, String gitBlitPort, String userName, String password) {
        // 1. 校验
        Assert.isTrue(StrUtil.isAllNotBlank(gitBlitIp, gitBlitPort, userName, password), "参数不得为空，请检查");

        // 2. 登录信息
        String userCookieValue = gitBlitUserCookieValue(gitBlitIp, gitBlitPort, userName, password);

        // 3. 获取用户仓库页面
        HttpResponse respHtmlhttpResponse = HttpUtil.createGet(StrUtil.format("http://{}:{}/repositories/", gitBlitIp, gitBlitPort))
                .header("Cookie", userCookieValue, true)
                .execute();
        String htmlBody = respHtmlhttpResponse.body();

        Document htmlBodyParse = Jsoup.parse(htmlBody);

        Elements respRowElements = htmlBodyParse.select("table[class='repositories'] tbody:nth-child(2) tr");

        List<String> result = CollUtil.newArrayList();
        for (int rowIndex = 1; rowIndex < CollUtil.size(respRowElements); rowIndex++) {
            Element rowElement = CollUtil.get(respRowElements, rowIndex);
            String respName = StrUtil.trim(rowElement.selectFirst("a").text());
            result.add(respName);
        }


        return result;
    }

}
